/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.great.functionalCore;

import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import br.great.beans.*;
import br.great.exception.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.*;
import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import java.util.regex.* ;
import java.util.Date;

/**
 *
 * @author C�line DEFAUT
 */
public class PhotoCreator {
    
    private static String dossier;

    public PhotoCreator(){
    }
    
    private static String getDossier(String uri){
        int i = uri.lastIndexOf("\\");
        if(i>=0)
            return uri.substring(0,i+1);
        else
            return null;
    }
    
    public static Photo createPhoto(Photo photo, int typeCollection){
        try{
            // lecture de l'ontologie
            System.out.print("uri:" + photo.getURIPhoto()); //Teste - Andre
            String uriAnnotations = photo.getURIAnnotations();
            System.out.print("uriAnnotaions:" + uriAnnotations); //Teste - Andre
            dossier = getDossier(uriAnnotations);
            FileInputStream in = new FileInputStream(uriAnnotations);
            Model model = ModelFactory.createMemModelMaker().createModel();
            model.read(in,null); 
            in.close();
            //String queryContentAnnotation = "PREFIX dc:<http://purl.org/dc/elements/1.1/> PREFIX ctxtphoto:<http://www-lsr.imag.fr/users/Windson.Viana/ontologies/ContextPhoto.owl#> PREFIX ctxt:<http://www-lsr.imag.fr/users/Windson.Viana/ontologies/ContextTopOntology.owl#> PREFIX nexif:<http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#> PREFIX georss:<http://www.georss.org/georss/> PREFIX gml:<http://www.opengis.net/gml/>  SELECT ?date ?text ?tag ?coor ?id ?model ?creator ?device ?temp ?unit {{?photo nexif:dateTime ?date} UNION {?photo ctxtphoto:content_annotation ?t. ?t ctxtphoto:tag ?tag} UNION {?photo ctxtphoto:content_annotation ?txt.?txt ctxtphoto:textual_description ?text} UNION { ?photo ctxtphoto:shot_context ?ctxt.?ctxt  ctxt:hasContextElement ?place.?place a ctxtphoto:Place.?place georss:where ?point. ?point gml:pos ?coor.} UNION {?p nexif:imageUniqueID ?id} UNION {?p nexif:model ?model} UNION {?p2 dc:creator ?creator} UNION{?p ctxtphoto:bluetoothAddress ?device} UNION {?a ctxtphoto:temperature_value ?temp. ?a ctxtphoto:temperature_unit ?unit}}";
            String queryContentAnnotation = "PREFIX dc:<http://purl.org/dc/elements/1.1/> PREFIX ctxtphoto:<http://www-lsr.imag.fr/users/Windson.Viana/ontologies/ContextPhoto.owl#> PREFIX ctxt:<http://www-lsr.imag.fr/users/Windson.Viana/ontologies/ContextTopOntology.owl#> PREFIX nexif:<http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#> PREFIX georss:<http://www.georss.org/georss/> PREFIX gml:<http://www.opengis.net/gml/> " +
                " SELECT ?photoURI ?date ?text ?tag ?coor ?id ?model ?creator ?device ?temp ?unit ?weather" +
                " {{?photo nexif:dateTime ?date} UNION {?photo ctxtphoto:content_annotation ?t. ?t ctxtphoto:tag ?tag} " +
                " UNION {?photo ctxtphoto:content_annotation ?txt.?txt ctxtphoto:textual_description ?text} " +
                " UNION { ?photo ctxtphoto:shot_context ?ctxt.?ctxt  ctxt:hasContextElement ?place.?place georss:where ?point. ?point gml:pos ?coor.} " +
                " UNION {?p nexif:imageUniqueID ?id} " +
                " UNION {?p nexif:model ?model} " +
                " UNION {?p nexif:fileSource ?photoURI} " +
                " UNION {?p2 dc:creator ?creator} " +
                " UNION{?p ctxtphoto:bluetoothAddress ?device} " +            
                " UNION {?a2 ctxtphoto:temperature_value ?temp. ?a2 ctxtphoto:temperature_unit ?unit. ?a ctxtphoto:weatherCondition ?weather} " +
                " }";
            Query query1 = QueryFactory.create(queryContentAnnotation);
            QueryExecution qe1 = QueryExecutionFactory.create(query1, model);
            ResultSet results1 = qe1.execSelect();
            String xml = ResultSetFormatter.asXMLString(results1);
            DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document document = parser.parse(new InputSource(new StringReader(xml)));
            Element root = (Element) document.getDocumentElement();
            
            // r�cup�ration des informations utiles pour les d�ductions : date et heure, coordonn�es, commentaires, tag, description
//System.out.println ("XML:"+xml);
            // uniqID
            String id = getID(root);
            photo.setUniqID(id);
            
            // model
            String m = getModel(root);
            photo.setModel(m);
            
            // creator
            String creator = getCreator(root);
            photo.setCreator(creator);
                      
            // textual description
            String textualDescription = getTextualDescription (root);
            photo.setContentAnnotation(textualDescription);
            
            // tags
            Vector<Tag> tags = getTags(root);
            photo.setTags(tags);
            
            // coordonn�es GPS
            String point = getPoint(root);
            Point coor = getCoordinate(point);
            photo.setCoor(coor);
            
            // uriPhoto pour FLICKR
            if (typeCollection==1){
                String uriPhoto = getURIPhoto (root);
                photo.setURIPhoto(uriPhoto);
            }
//System.out.println("photoURI is : "+uriPhoto);
            // date
            String date = getDate(root);
            Date d = constructDate(date);
            photo.setDateTime(d);
//            String part_of_day = getPartOfDay(d);
//            photo.setPartOfDay(part_of_day);
            
            // weather
            String temp = getTemp(root);
            String unit = getUnit(root);
            Temperature t = new Temperature();   
               if(temp!=null){
                   //  System.out.println("Temp:"+temp);
                t.setValue(Float.parseFloat(temp));
                t.setType(unit);
                //System.out.println("Unit:"+unit);
                
            }
            photo.setTemperature(t);
            
            Weather w = new Weather();
            String weatherClouds=getWeather(root);
           // System.out.println("Clouds:"+weatherClouds);
            w.setDescription(weatherClouds);
            photo.setWeather(w);
            
            // devices
            Vector<String> devices = getDevices(root);
            photo.setDevices(devices);
                        
        }catch(Exception ex){
            ex.printStackTrace();
            Logger.getLogger(PhotoCreator.class.getName()).log(Level.SEVERE, null, ex);
        }
        return photo;
    }
    
    
    private static String getWeather(Node node) {
         String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("weather"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getWeather(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }

        return null;
    }

    private static String getTemp (Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("temp"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getTemp(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }

        return null;
    } 
    
    private static String getUnit (Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("unit"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getUnit(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }

        return null;
    } 
    
    private static String getTextualDescription (Node node){
        try{
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("text"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getTextualDescription(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }

       }catch(Exception e){
            return "No description";
        }  
       return "No description"; 
    } 
    
    private static String getID (Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("id"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getID(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }

        return null;
    } 
    
    private static String getModel (Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("model"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getModel(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }
        return null;
    }
    
    private static String getCreator (Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("creator"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getCreator(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }

        return null;
    } 
    
    private static Vector<Tag> getTags(Node node){
        Vector<Tag> tags = new Vector<Tag>();
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("tag"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            Tag tag = new Tag();
                            tag.setTAG_VALUE(c.getNodeValue());
                            tags.add(tag);
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    Vector<Tag> res = getTags(nodeList.item(i));
                    if(res.size()>0){
                        tags.addAll(res);
                    }
            }
        }
        return tags;
    }    
    
    private static Vector<String> getDevices(Node node){
        Vector<String> devices = new Vector<String>();
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("device"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            devices.add(c.getNodeValue());
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    Vector<String> res = getDevices(nodeList.item(i));
                    if(res.size()>0){
                        devices.addAll(res);
                    }
            }
        }
        return devices;
    }
    
    private static String getPoint(Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            //System.out.println("value binding : "+node.getNodeValue());
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            //System.out.println("value name : "+n.getNodeValue());
            if((n!= null) && (n.getNodeValue().equals("coor"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                String res = getPoint(nodeList.item(i));
                if(res!=null){
                    return res;
                }
            }
        }

        return null;
    }
    
    private static Point getCoordinate (String point){
        Point coor = null;
        int index = point.indexOf(" ");
        if (index > 0){
            coor = new Point(); 
            double lat;
            double lon;
            if(point.charAt(0)=='-')
                lat = - Double.parseDouble(point.substring(1, index));
            else
                lat = Double.parseDouble(point.substring(0, index));
            coor.setLatitude(lat);
            if(point.charAt(index+1)=='-')
                lon = - Double.parseDouble(point.substring(index+2));
            else
                lon = Double.parseDouble(point.substring(index+1));
            coor.setLongitude(lon);
        }
        return coor;
    }
    
    private static String getDate(Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            //System.out.println("value binding : "+node.getNodeValue());
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            //System.out.println("value name : "+n.getNodeValue());
            if((n!= null) && (n.getNodeValue().equals("date"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                String res = getDate(nodeList.item(i));
                if(res!=null){
                    return res;
                }
            }
        }

        return null;
    }
    
    private static String getURIPhoto (Node node){
        String nodeName = node.getNodeName();
        if(nodeName.equals("binding")){
            NamedNodeMap nnm = node.getAttributes();
            Node n = nnm.getNamedItem("name");
            if((n!= null) && (n.getNodeValue().equals("photoURI"))){
                if(node.hasChildNodes()){
                    NodeList nodeListAnnot = node.getChildNodes();
                    int size = nodeListAnnot.getLength();
                    for (int i = 0; i < size; i++) {
                        Node l = nodeListAnnot.item(i);
                        if(l.getNodeName().equals("literal")){
                            Node c = l.getFirstChild();
                            return c.getNodeValue();
                        }
                    }
                }
            }
        }
        
        if(node.hasChildNodes()){
            NodeList nodeList = node.getChildNodes();
            int size = nodeList.getLength();
            for (int i = 0; i < size; i++) {
                    String res = getURIPhoto(nodeList.item(i));
                    if(res!=null){
                        return res;
                    }
            }
        }
        return null;
    }
    
    private static Date constructDate (String date){
        Date d = null;
        Pattern p = Pattern.compile("([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})");
        Matcher m = p.matcher(date);
        if(m.matches()){
            d = new Date(Integer.parseInt(m.group(1))-1900, Integer.parseInt(m.group(2))-1, Integer.parseInt(m.group(3)), Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)), Integer.parseInt(m.group(6)));
        }
        return d;
    }

   
    
//    public static void main(String[] args){
//        Photo p = new Photo();
//        p.setURIAnnotations("P:\\Bureau\\projet_PHOTOMAP\\CONTEXT_PHOTO\\fichiersOwlMobile\\RomanForum1.owl");
//        createPhoto(p);
//    }
}
